package com.fly.hello.job;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import com.fly.core.annotation.OnceSchedule;
import com.fly.core.utils.SpringContextUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * ScheduleJob
 * 
 * @author 00fly
 * @version [版本号, 2022年11月30日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
@Component
@Profile("dev")
public class ScheduleJob
{
    private String welcome;
    
    @Autowired
    ApplicationContext context;
    
    @Autowired
    JdbcTemplate jdbcTemplate;
    
    String key = "test";
    
    /**
     * PostConstruct注解的方法将会在依赖注入完成后被自动调用<BR>
     * Constructor >> Autowired >> PostConstruct
     */
    @PostConstruct
    private void init()
    {
        log.info("==================ScheduleJob @PostConstruct");
        welcome = "Hello 00fly in ScheduleJob, profile: " + SpringContextUtils.getActiveProfile(context);
    }
    
    /**
     * 7-23点每10秒执行<br>
     * 
     */
    @OnceSchedule(nextSeconds = 9)
    @Scheduled(cron = "0/10 * 7-23 * * ?")
    public void run()
    {
        String value = String.valueOf(RandomUtils.nextInt(0, 10));
        if (updateSuccess(value))
        {
            log.info("**** update to {}", value);
        }
    }
    
    @Scheduled(fixedDelay = 60000L)
    public void run1()
    {
        // 演示MDC和NDC
        final String id = UUID.randomUUID().toString();
        final String profile = SpringContextUtils.getActiveProfile();
        ThreadContext.put("id", id);
        ThreadContext.push(profile);
        try
        {
            if (RandomUtils.nextInt(1, 20) == 1)
            {
                final int i = 1 / 0; // 抛出异常
                Assert.notNull(i, "The value must be null");
            }
        }
        catch (Exception e)
        {
            log.error("系统出错：" + e.getMessage(), e);
        }
        log.info("★★★★★★★  {} ==> {}", id, welcome);
        ThreadContext.clearAll();
    }
    
    /**
     * 是否更新成功
     * 
     * @param value
     * @return
     */
    private boolean updateSuccess(String value)
    {
        List<Map<String, Object>> list = jdbcTemplate.queryForList("select key_value from t_run_info where key_name=? limit 1", key);
        String keyValue = list.isEmpty() ? null : list.get(0).get("key_value").toString();
        log.info("load from db: {}, new: {}", keyValue, value);
        
        // 数据发生变化才更新
        if (!StringUtils.equals(value, keyValue))
        {
            int count = jdbcTemplate.update("update t_run_info set key_value=? where key_name=?", value, key);
            if (count == 0)
            {
                count = jdbcTemplate.update("insert into t_run_info(key_name, key_value) values(?, ?)", key, value);
            }
            return count > 0;
        }
        return false;
    }
    
    /**
     * fixedDelay 7秒
     */
    // @Scheduled(fixedDelay = 7000)
    public void run2()
    {
        try
        {
            TimeUnit.SECONDS.sleep(5); // 注意这儿的休眠时间
            log.error("#### {}", welcome);
        }
        catch (Exception e)
        {
            log.error(e.getMessage(), e);
        }
    }
    
    /**
     * 测试日志打印
     */
    // @Scheduled(fixedRate = 5000)
    public void run3()
    {
        log.trace("★★★★★★★★ {}", welcome);
        log.debug("★★★★★★★★ {}", welcome);
        log.info("★★★★★★★★ {}", welcome);
        log.warn("★★★★★★★★ {}", welcome);
        log.error("★★★★★★★★ {}", welcome);
    }
}
